package com.fulihui.information.biz.content.impl;

import com.fulihui.information.biz.content.ContentCommentsBizManager;
import com.fulihui.information.biz.content.ContentCommentsReplyBizManager;
import com.fulihui.information.biz.content.impl.handler.ContentCommentsHandler;
import com.fulihui.information.biz.counter.ContentCommentTimesOperableCounter;
import com.fulihui.information.core.db.CommentsOnOffDB;
import com.fulihui.information.core.repository.ContentCommentsPraiseRepository;
import com.fulihui.information.core.repository.ContentCommentsReplyRepository;
import com.fulihui.information.core.repository.ContentCommentsRepository;
import com.fulihui.information.core.repository.ContentRepository;
import com.fulihui.information.dal.dataobj.InfoContentComments;
import com.fulihui.information.dal.dataobj.InfoContentCommentsExample;
import com.fulihui.information.dal.dataobj.InfoContentCommentsPraiseExample;
import com.fulihui.information.dal.dataobj.InfoContentCommentsReplyExample;
import com.fulihui.information.dto.ContentDTO;
import com.fulihui.information.dto.InfoContentCommentsDTO;
import com.fulihui.information.dto.InfoContentCommentsPraiseDTO;
import com.fulihui.information.dto.InfoContentCommentsReplyDTO;
import com.fulihui.information.model.UserContentOperate;
import com.fulihui.information.request.ContentCommentsCreateRequest;
import com.fulihui.information.request.ContentCommentsQueryRequest;
import com.fulihui.information.request.ContentCommentsReplyQueryRequest;
import com.fulihui.information.request.ContentCommentsRequest;
import com.fulihui.information.result.ContentCommentsResponse;
import com.fulihui.integralbusiness.constants.IntegralBusinessFlags;
import com.fulihui.integralbusiness.producer.ZbusIntegralCreator;
import com.google.common.collect.Maps;
import org.apache.commons.codec.binary.Base64;
import org.near.dal.sequence.SeqKit;
import org.near.toolkit.common.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;

import static com.fulihui.information.enums.ECommentsStatus.*;

/**
 * Created by LM on 2017/4/9.
 */
@Component
public class ContentCommentsBizManagerImpl implements ContentCommentsBizManager {

    @Autowired
    private ContentCommentsRepository          commentsRepository;
    @Autowired
    private ContentCommentsReplyRepository     commentsReplyRepository;
    @Autowired
    private TransactionTemplate                transactionTemplate;
    @Autowired
    private CommentsOnOffDB                    commentsOnOffDB;
    @Autowired
    private ContentCommentsReplyBizManager     commentsReplyBizManager;
    @Autowired
    private ContentCommentsPraiseRepository    commentsPraiseRepository;
    @Autowired
    private ContentCommentTimesOperableCounter contentCommentTimesOperableCounter;
    @Autowired
    private ZbusIntegralCreator                zbusIntegralCreator;
    @Autowired
    private ContentCommentsHandler             commentsHandler;
    @Autowired
    private ContentRepository                  contentRepository;

    @Override
    public String createComments(ContentCommentsCreateRequest request) {
        InfoContentComments comments = new InfoContentComments();
        BeanUtils.copyProperties(request, comments);
        // 默认未审核
        comments.setStatus(UNCHECK.getCode());
        // 生成序列id
        comments.setId(SeqKit.genId() + "");
        // 默认点赞数为零
        comments.setPraiseTotal(0l);
        // 默认回复数为零
        comments.setReplyTotal(0l);
        // 设置内容标题
        comments
            .setContentTitle(getContentTitle(request.getContentId(), request.getContentTitle()));
        // 评论内容编码
        comments.setCommentContent(Base64
            .encodeBase64String(request.getCommentContent().getBytes()));
        boolean result = commentsRepository.create(comments);
        if (result) {
            /**
             * 累计文章评论数
             */
            UserContentOperate operate = new UserContentOperate();
            operate.setContentId(request.getContentId());
            contentCommentTimesOperableCounter.operate(operate);
            /**
             * 积分返利
             */
            try {
                Map<String, Object> msg = Maps.newHashMap();
                msg.put("userId", request.getUserId());
                msg.put("commentsId", comments.getId());
                zbusIntegralCreator.create(IntegralBusinessFlags.COMMENTS, msg);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        } else {
            return null;
        }
        return comments.getId();
    }

    @Override
    public void praiseTotal(String commentsId, String userId, String contentId) {
        commentsHandler.praiseTotal(commentsId, userId, contentId);
    }

    @Override
    public void replyTotal(String commentsId) {
        commentsHandler.replyTotal(commentsId);
    }

    @Override
    public List<InfoContentCommentsDTO> queryPage(ContentCommentsQueryRequest request) {
        InfoContentCommentsExample example = genExample(request);
        // 排序
        if (StringUtil.isNotBlank(request.getOrderByClause())) {
            example.setOrderByClause(request.getOrderByClause());
        }
        example.setLimit(request.getRows());
        example.setOffset(request.start4Mysql());
        return commentsRepository.queryPage(example);
    }

    @Override
    public ContentCommentsResponse<InfoContentCommentsDTO> queryPageExt(ContentCommentsQueryRequest request,
                                                                        boolean onOff) {
        ContentCommentsResponse<InfoContentCommentsDTO> response = new ContentCommentsResponse<InfoContentCommentsDTO>();
        /**
         * 查询文章评论
         */
        InfoContentCommentsExample example = genExampleExt(request, onOff);
        // 排序
        if (StringUtil.isNotBlank(request.getOrderByClause())) {
            example.setOrderByClause(request.getOrderByClause());
        }
        example.setLimit(request.getRows());
        // 数据偏移量
        if (request.getNum() != null) {
            example.setOffset(request.start4Mysql() - request.getNum() >= 0 ? request.start4Mysql()
                                                                              - request.getNum()
                : 0);
        } else {
            example.setOffset(request.start4Mysql());
        }
        // 分页查询
        List<InfoContentCommentsDTO> commentsDTOList = commentsRepository.queryPage(example);
        Map<String, InfoContentCommentsDTO> commentsDTOMap = new HashMap<>(commentsDTOList.size());
        // 取出id方便一次查询出所有回复
        List<String> commentsIds = new ArrayList<>(commentsDTOList.size());
        // 最大时间&偏移量
        final Long[] maxTime_num = { null, 0l };
        if (commentsDTOList != null && commentsDTOList.size() > 0) {
            commentsDTOList.forEach(infoContentCommentsDTO -> {
                // 默认第一条为最大时间
                if (maxTime_num[0] == null) {
                    if (request.getEndDate() == null) {
                        maxTime_num[0] = infoContentCommentsDTO.getGmtCreate().getTime();
                    } else {
                        maxTime_num[0] = request.getEndDate().getTime();
                    }
                }
                // 与最大时间相等
                if (infoContentCommentsDTO.getGmtCreate().getTime() == maxTime_num[0]) {
                    // +1
                    maxTime_num[1] = maxTime_num[1] + 1;
                }
                commentsDTOMap.put(infoContentCommentsDTO.getId(), infoContentCommentsDTO);
                commentsIds.add(infoContentCommentsDTO.getId());
                /**
                 * 查询评论回复
                 */
                ContentCommentsReplyQueryRequest commentsReplyQueryRequest = new ContentCommentsReplyQueryRequest();
                commentsReplyQueryRequest.setCommentsId(infoContentCommentsDTO.getId());
                commentsReplyQueryRequest.setUserId(request.getUserId());
                InfoContentCommentsReplyExample commentsReplyExample = commentsReplyBizManager
                    .genExampleExt(commentsReplyQueryRequest, onOff);
                commentsReplyExample.setLimit(3);
                commentsReplyExample.setOrderByClause("gmt_create ASC");
                // 默认查询查询3条数据
                List<InfoContentCommentsReplyDTO> commentsReplyDTOList = commentsReplyRepository
                    .queryPage(commentsReplyExample);
                if (!CollectionUtils.isEmpty(commentsReplyDTOList)) {
                    infoContentCommentsDTO.setCommentsReplyList(commentsReplyDTOList);
                }
            });
            /**
             * 是否点赞
             */
            if (StringUtil.isNotBlank(request.getUserId())) {
                // 查询用户点赞信息
                List<InfoContentCommentsPraiseDTO> commentsPraiseDTOs = queryCommentsPraise(
                    request.getUserId(), commentsIds);
                if (commentsPraiseDTOs != null && commentsPraiseDTOs.size() > 0) {
                    commentsPraiseDTOs.forEach(infoContentCommentsPraiseDTO -> {
                        commentsDTOMap.get(infoContentCommentsPraiseDTO.getCommentId()).setPraise(
                            true);
                    });
                }
            }
        }
        response.setValues(commentsDTOList);
        response.setMaxGmtCreate(maxTime_num[0]);
        response.setNum(maxTime_num[1].intValue());
        return response;
    }

    @Override
    public long queryPageCount(ContentCommentsQueryRequest request) {
        InfoContentCommentsExample example = genExample(request);
        return commentsRepository.countByExample(example);
    }

    @Override
    public boolean removeContentComments(ContentCommentsRequest request) {
        InfoContentComments comments = new InfoContentComments();
        comments.setId(request.getCommentsId());
        comments.setStatus(DELETE.getCode());
        comments.setOperator(request.getOperator());
        return transactionTemplate.execute(status -> {
            // 删除评论
            boolean result = commentsRepository.update(comments);
            /**
             * 级联删除评论回复
             */
            if (result) {
                commentsReplyRepository.removeByCommentsId(request.getCommentsId());
            }
            if (!result) {
                status.setRollbackOnly();
            }
            return result;
        });
    }

    @Override
    public long queryPageCountExt(ContentCommentsQueryRequest request, boolean onOff) {
        InfoContentCommentsExample example = genExampleExt(request, onOff);
        return commentsRepository.countByExample(example);
    }

    @Override
    public InfoContentCommentsDTO queryByPK(ContentCommentsRequest request) {
        InfoContentCommentsDTO contentCommentsDTO = commentsRepository.selectByPrimaryKey(request
            .getCommentsId());
        if (StringUtil.isNotBlank(request.getUserId())) {
            // 查询用户点赞信息
            List<InfoContentCommentsPraiseDTO> commentsPraiseDTOs = queryCommentsPraise(
                request.getUserId(), Arrays.asList(contentCommentsDTO.getId()));
            if (commentsPraiseDTOs != null && commentsPraiseDTOs.size() > 0) {
                contentCommentsDTO.setPraise(true);
            }
        }
        return contentCommentsDTO;
    }

    @Override
    public List<InfoContentCommentsDTO> queryPageUserComments(ContentCommentsQueryRequest request) {
        InfoContentCommentsExample example = genExample(request);
        // 数据偏移量
        if (request.getNum() != null) {
            example.setOffset(request.start4Mysql() - request.getNum() >= 0 ? request.start4Mysql()
                                                                              - request.getNum()
                : 0);
        } else {
            example.setOffset(request.start4Mysql());
        }
        example.setLimit(request.getRows());
        example.setOrderByClause(request.getOrderByClause());
        return commentsRepository.queryPage(example);
    }

    @Override
    public String getContentTitle(String contentId, String contentTitle) {
        if (StringUtil.isNotBlank(contentTitle)) {
            return contentTitle;
        }
        // 查询内容
        ContentDTO contentDTO = contentRepository.detail(contentId);
        if (contentDTO == null) {
            return null;
        }
        return StringUtil.isNotBlank(contentDTO.getTitle()) ? contentDTO.getTitle() : contentDTO
            .getListComment();
    }

    private InfoContentCommentsExample genExample(ContentCommentsQueryRequest request) {
        InfoContentCommentsExample example = new InfoContentCommentsExample();
        InfoContentCommentsExample.Criteria criteria = example.createCriteria();
        if (StringUtil.isNotBlank(request.getCommentsId())) {
            criteria.andIdEqualTo(request.getCommentsId());
        }
        if (StringUtil.isNotBlank(request.getContentId())) {
            criteria.andContentIdEqualTo(request.getContentId());
        }
        if (request.getStartDate() != null) {
            criteria.andGmtCreateGreaterThanOrEqualTo(request.getStartDate());
        }
        if (request.getEndDate() != null) {
            criteria.andGmtCreateLessThan(request.getEndDate());
        }
        if (StringUtil.isNotBlank(request.getUserId())) {
            criteria.andUserIdEqualTo(request.getUserId());
        }
        if (!CollectionUtils.isEmpty(request.getStatus())) {
            criteria.andStatusIn(request.getStatus());
        }
        return example;
    }

    private InfoContentCommentsExample genExampleExt(ContentCommentsQueryRequest request,
                                                     boolean onOff) {
        InfoContentCommentsExample example = new InfoContentCommentsExample();
        InfoContentCommentsExample.Criteria criteria0 = example.createCriteria();
        if (StringUtil.isNotBlank(request.getContentId())) {
            criteria0.andContentIdEqualTo(request.getContentId());
        }
        if (onOff) { // 开关启用，先显示后审核
            criteria0.andStatusIn(Arrays.asList(CHECK.getCode(), UNCHECK.getCode()));
        } else { // 开关关闭，先审核后显示 or 自己的评论
            // 已审核
            criteria0.andStatusEqualTo(CHECK.getCode());
            if (StringUtil.isNotBlank(request.getUserId())) {
                // or自己的评论
                InfoContentCommentsExample.Criteria criteria1 = example.or();
                criteria1.andContentIdEqualTo(request.getContentId());
                criteria1.andStatusEqualTo(UNCHECK.getCode());
                criteria1.andUserIdEqualTo(request.getUserId());
                if (request.getEndDate() != null) {
                    criteria1.andGmtCreateLessThan(request.getEndDate());
                }
            }
        }
        return example;
    }

    private List<InfoContentCommentsPraiseDTO> queryCommentsPraise(String userId,
                                                                   List<String> commentsIds) {
        InfoContentCommentsPraiseExample commentsPraiseExample = new InfoContentCommentsPraiseExample();
        commentsPraiseExample.createCriteria().andCommentIdIn(commentsIds).andUserIdEqualTo(userId);
        List<InfoContentCommentsPraiseDTO> commentsPraiseDTOs = commentsPraiseRepository
            .selectByExample(commentsPraiseExample);
        return commentsPraiseDTOs;
    }

}
